/*
 *  StaticsUtilityTester.cpp
 *  MarketDataAnalyzer 2
 *
 *  Created by jiro on 10/10/03.
 *  Copyright 2010 jiro music. All rights reserved.
 *
 */

#include "StaticsUtilityTester.h"
#include "../StaticsUtility.h"
#include "../InterpolatedData.h"
#include "../InterpolatedData2.h"
#include "../NotInterpolatedData.h"
#include "../../../Utility/CustomAssert.h"
#include "../../Common/DbOperator.h"
#include "../../DbTypes/DbUtility.h"
#include "libpq-fe.h"

void StaticsUtilityTester::TestAll()
{
	Test_CalcMean();
	Test_CalcVariance();
	Test_CalcStandardDeviation(); 
	Test_CalcCovariance();
	Test_CalcCorelationCoefficient();

}

void StaticsUtilityTester::Test_CalcMean()
{
	vector<double> values;
	values.push_back( 1 );
	values.push_back( 2 );
	values.push_back( 3 );
	values.push_back( 4 );
	
	InterpolatedData* data = new NotInterpolatedData( values, 4 );

	AssertEqual( StaticsUtility::CalcMean( data ), ( 1. + 2. + 3. + 4. ) / 4. );

	delete data;
}

void StaticsUtilityTester::Test_CalcVariance()
{	
	Test_CalcVariance_000();
	Test_CalcVariance_001();
	
}

void StaticsUtilityTester::Test_CalcVariance_000()
{
	vector<double> values;
	values.push_back( 1 );
	values.push_back( 2 );
	values.push_back( 3 );
	values.push_back( 4 );
	
	InterpolatedData* data = new NotInterpolatedData( values, 4 );
	double mean = StaticsUtility::CalcMean( data );
	double variance = 0.0;
	for ( int i = 0; i < 4; i++ ) 
	{
		variance += pow( values[ i ] - mean, 2.0 );
	}
	variance /= 3;

	AssertEqual( StaticsUtility::CalcVariance( data ), variance );

	delete data;
}

void StaticsUtilityTester::Test_CalcVariance_001()
{
	id sql = @"select variance( adjusted_end_price ) from stock_exchange_ja_table where code ='1301' and '2009-1-1' <= exchange_date "
			 @"and exchange_date < '2010-1-1'; ";
	id dbOperator = [ DbOperator defaultOperator ];
	PGresult* res = nil;
	if ( DbResponse_Success != [ dbOperator executeQuery:sql intoResult: & res ] ) {
		NSLog( @"db fail %@", [ dbOperator errorMessage ] );
	}
	double vari = [ DbUtility parseAsDouble: PQgetvalue( res, 0, 0 ) ];
	PQclear( res );

	sql = @"select adjusted_end_price from stock_exchange_ja_table where code ='1301' and '2009-1-1' <= exchange_date "
			@"and exchange_date < '2010-1-1'; ";
	if ( DbResponse_Success != [ dbOperator executeQuery:sql intoResult: & res ] ) {
		NSLog( @"db fail %@", [ dbOperator errorMessage ] );
	}
	int count = PQntuples( res );
	vector<double> values;
	for ( int i = 0; i < count; i++ ) {
		values.push_back( [ DbUtility parseAsDouble: PQgetvalue( res, i, 0 ) ] );
	}
	NotInterpolatedData data( values, values.size() );
	double vari2 = StaticsUtility::CalcVariance( & data );
	PQclear( res );
	
	AssertEqualWithError( vari, vari2, 0.00001 );
	
	[ dbOperator disconnect ];
}
	
void StaticsUtilityTester::Test_CalcStandardDeviation()
{
	vector<double> values;
	values.push_back( 1 );
	values.push_back( 2 );
	values.push_back( 3 );
	values.push_back( 4 );
	
	InterpolatedData* data = new NotInterpolatedData( values, 4 );
	double mean = StaticsUtility::CalcMean( data );
	double variance = 0.0;
	for ( int i = 0; i < 4; i++ ) 
	{
		variance += pow( values[ i ] - mean, 2.0 );
	}
	variance /= 3;

	AssertEqual( StaticsUtility::CalcStandardDeviation( data ), pow( variance, 0.5 ) );

	delete data;
}

void StaticsUtilityTester::Test_CalcCovariance()
{
	vector<double> values;
	values.push_back( 1 );
	values.push_back( 2 );
	values.push_back( 3 );
	values.push_back( 4 );
	
	InterpolatedData* data = new NotInterpolatedData( values, 4 );
	double mean = StaticsUtility::CalcMean( data );
	double covariance = 0.0;
	for ( int i = 0; i < 4; i++ ) 
	{
		covariance += ( values[ i ] - mean ) * ( values[ i ] - mean );
	}
	covariance /= 4.0;

	AssertEqual( StaticsUtility::CalcCovariance( data, data ), covariance );

	delete data;
}

void StaticsUtilityTester::Test_CalcCorelationCoefficient()
{
	vector<double> values;
	values.push_back( 1 );
	values.push_back( 2 );
	values.push_back( 3 );
	values.push_back( 4 );

	vector<double> values2;
	values2.push_back( -1. );
	values2.push_back( -2. );
	values2.push_back( -3. );
	values2.push_back( -4. );

	vector<double> values3;
	values3.push_back( -1. );
	values3.push_back( -1. );
	values3.push_back( -1. );
	values3.push_back( -1. );

	vector<double> values4;
	values4.push_back( -1. );
	values4.push_back( 1. );
	values4.push_back( -1. );
	values4.push_back( 1. );

	InterpolatedData* data = new NotInterpolatedData( values, 4 );	
	InterpolatedData* data2 = new NotInterpolatedData( values2, 4 );	
	InterpolatedData* data3 = new NotInterpolatedData( values3, 4 );
	InterpolatedData* data4 = new NotInterpolatedData( values4, 4 );
	
	AssertEqualWithError( StaticsUtility::CalcCorelationCoefficient( data, data ), 0.75, 0.001 );
	AssertEqualWithError( StaticsUtility::CalcCorelationCoefficient( data, data2 ), -0.75, 0.001 );
	AssertEqualWithError( StaticsUtility::CalcCorelationCoefficient( data, data3 ), 0, 0.001 );
	AssertEqualWithError( StaticsUtility::CalcCorelationCoefficient( data, data4 ), 0.33541, 0.001 );
	
	delete data;
	delete data2;
	delete data3;
}
